home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************************\
- * *
- * *
- * ***** ***** *
- * ***** ***** *
- * ***** ***** *
- * ***** ***** *
- * ***** ***** *
- * ***** ***** *
- * ***** ***** *
- * ***** ***** The Firmware. The Net. *
- * ***** ***** Portable. Compatible. *
- * ***** ***** Public Domain. *
- * ***** ***** By NORD><LINK. *
- * *
- * *
- * *
- * L2A.C - Level 2, Teil 1 *
- * *
- * angelegt: DC4OX *
- * modifiziert: *
- * *
- * G8KBB version X1J- added register keyword to compress code a bit *
- * add audit functions conditionally on MANAGED *
- * add KISS drivers conditionally on KISSMODE *
- * add MHEARD command audit hooks on MONITORCMD *
- * add Auditing support *
- * add Access Control List support conditionally on ACL *
- * add support for welcome msg on alias uplink *
- * add support for level 2 stats gathering *
- * add MTU command support optionally on MOD_MTU *
- * add nodigi control on uplinks to node *
- * add support for 3 aliases for BBS, HOST & DXCluster *
- * remove spurious '== 1' and similar structures *
- * *
- * September 1993 - released as TheNet X-1J *
- * *
- * Add l3 heard list optionally on L3MONITOR *
- * Correct buffer loss bug in l2rx() *
- * Minor speedups to the code *
- * *
- * Released as TheNet X-1J release 4, January 1995 *
- \**************************************************************************/
-
-
-
-
-
- /* Includes */
- /**************************************************************************/
-
- #include "all.h" /* allgemeine Festlegungen */
- #include "tntyp.h" /* Festlegungen/Datenstrukturen fuer den Level 2 */
- #include "l2s.h" /* Zugriff auf die State-Tabellen */
- #include "l2ext.h" /* globale Variable / nicht int-Funktionen */
-
-
- #ifdef MANAGED
- #ifdef BANKED
- extern char L2audit[];
- #else
- char L2audit[] = "L2 `"; /* this string identifies level 2 audit msgs */
- #endif
- #endif
-
-
- /**************************************************************************\
- * *
- * "level 2" *
- * *
- * Der Level 2. Es werden alle Level-2-internen Aktionen ausgefuehrt und *
- * Meldungen an hoehere Level weitergegeben (Informationstransfer von/zum *
- * Level 2 und Kommandos an den Level 2 geschehen von ausserhalb). *
- * *
- * *
- * Der Level 2 laeuft wie folgt ab : *
- * *
- * - Aufruf von l2init() *
- * *
- * - zyklisches Aufrufen von l2() und l2timr(ticks) *
- * *
- * Statusaenderungen im Level 2 (Connects, Disconnects, Failures, usw.) *
- * werden hoeheren Leveln vom Level 2 aus ueber *
- * *
- * l2tolx(<status>) -> l2tol3(<status>), l2tol7(<status>,lnkpoi,2) *
- * *
- * mitgeteilt. *
- * *
- * Ein Connectwunsch wird dem Level 2 ueber das Besetzen eines leeren *
- * Linkblocks mit Quell- und Ziel- sowie Digicalls und Aufrufen von *
- * newlnk() mitgeteilt (lnkpoi zeigt auf Linkblock !). *
- * Ein newlnk() auf einen bestehenden Link erzeugt einen Link Reset. *
- * *
- * Ein Disconnectwunsch (oder bei mehrmaligem Aufruf der sofortige *
- * Disconnect) wird ueber das Setzen von lnkpoi auf den jeweiligen *
- * Linkblock und Aufruf von dsclnk() erreicht. *
- * *
- * Der Informationstransfer zum Level 2 geschieht von aussen durch *
- * Aufruf von itolnk(...), vom Level 2 durch itolx(..), welches dann *
- * fmlink() aus dem hoeheren Level aufruft. *
- * *
- * Ueber sdui(..) koennen unproto-Pakete (UI-Frames) gesendet werden. *
- * *
- * Level-3-Pakete (Level-3-UI-Pakete oder Infopakete in Sequenz eines *
- * Level-2-3-Links) werden ausgefiltert und in die Level-3-Frameliste *
- * eingehaengt. *
- * *
- \**************************************************************************/
-
- VOID l2()
- {
- l2tx(); /* der Sender */
- l2rx(); /* der Empfaenger */
- l2rest(); /* sonstiges */
- }
-
-
-
-
-
- /**************************************************************************\
- * *
- * "level 2 transmitter" *
- * *
- * Falls Infopakete zu senden sind, laut Sendefenster keine Infopakete *
- * ausstehen, und laut Sendestatus auch gesendet werden duerfen, diese *
- * senden. *
- * *
- * Frames aus Gesendet-Liste holen und in die Monitorframeliste umhaengen *
- * (Firmware) oder deallokieren. Entsprechend dem Frameinhalt ggf. Timer 1 *
- * starten. *
- * *
- \**************************************************************************/
-
- VOID l2tx()
- {
- register unsigned n; /* Laufindex */
- register unsigned l2state; /* aktueller Linkstate */
- register MBHEAD *sfbp; /* Sendeframebufferpointer */
-
- for (n = LINKNMBR, lnkpoi = lnktbl; n != 0; --n, ++lnkpoi)
- if ( (l2state = lnkpoi->state) == L2SIXFER /* duerfen */
- || l2state == L2SRS /* wir was */
- || l2state == L2SDBS /* senden ? */
- || l2state == L2SRSDBS
- )
- if (lnkpoi->VS == lnkpoi->lrxdNR) /* nichts ausstehend ? */
- sdi(lnkpoi->k); /* dann Infos senden */
-
- while ((sfbp = stfl.head) != &stfl) /* Gesendetliste */
- { /* aufraeumen : */
- unlink(sfbp); /* Frame holen */
- if ((sfbp->l2fflg & L2FT1ST) != NO) /* ist T1 zu starten ? */
- { /* ja, Zeiger auf Link- */
- lnkpoi = sfbp->l2link; /* block (zum Frame) */
- setT1(); /* und T1 starten */
- }
-
- #ifdef FIRMWARE
- if (nmbfre > 64) /* falls noch genug */
- relink(sfbp,monfl.tail); /* Platz, Frame in den */
- else /* Monitor */
- #endif
-
- dealmb(sfbp); /* oder deallokieren */
- }
- }
-
-
-
-
-
- /**************************************************************************\
- * *
- * "level 2 receiver" *
- * *
- * Alle Frames aus der RX-Frameliste holen und analysieren. Kopie an *
- * Monitorliste, digipeaten oder in Level-3-Liste, falls erforderlich. *
- * Auf UI-Frames antworten, falls erforderlich. *
- * *
- * Reaktion entsprechend Protokoll, siehe unten. *
- * *
- \**************************************************************************/
-
- VOID l2rx()
- {
- char *source; /* Zeiger auf Quellrufzeichen/SSID */
- register unsigned l2state; /* aktueller Level 2 Linkstatus */
- register unsigned n; /* Laufindex */
- register MBHEAD *fbp; /* Framebufferpointer lokal */
- BOOLEAN tome; /* YES = Frame ist an mich */
- LNKBLK *lblkp; /* Linkblockpointer lokal */
-
-
-
- while ((fbp = rxfl.head) != &rxfl) /* solange empfangene */
- { /* Frames vorhanden */
- unlink(fbp); /* eins aus Liste holen */
-
- if (!takfhd(fbp)) /* Kopf analysieren, */
- { /* wenn nicht ok, dann */
- dealmb(fbp); /* wegwerfen und zum */
- continue; /* naechsten */
- }
-
- fbp->type = 2; /* wir sind im Level 2 */
-
- #ifdef STATSCMD
- L2HDCNT[fbp->l2port & MAXPORTMASK]++; /* bump heard packet count*/
- #endif
- #ifdef FIRMWARE
- if (nmbfre > 64) /* wenn genug Platz, */
- relink(cpyfb(fbp),monfl.tail); /* Kopie an Monitor */
- #endif
- #ifdef KISSMODE
- if( (crlmod == 3) && !ishost() && nmbfre > 64 ) /* if not host, and */
- send_to_other_port( cpyfb( fbp ) ); /* mode 3 and KISS, copy it */
- #endif
- #ifdef MONITORCMD
- if( mhlcount ) /* if heard list running */
- #ifdef L3MONITOR
- checkheard(&heardl, txfhdr, mhlcount);/* update heard list */
- #else
- checkheard();
- #endif
- #endif
- if (digipt(fbp) /*== YES*/) continue; /* ... nur Digipeater */
-
- if (rxfctl == L2CUI) /* UI-Frame, */
- { /* wenn an mich, und */
- if (istome(rxfhdr) /*== YES*/) /* Antwort erwuenscht, */
- { if (rxfPF != NO && rxfCR != NO) /* entsprechend */
- xdm(); /* beantworten */
- }
- lnkpoi = NULL; /* fuer tol3sw() */
- #ifdef KISSMODE
- if( (crlmod == 2) && !ishost() && /* kiss copy, but only if*/
- nmbfre > 64 && !cmpid( myid, rxfhdr ) ) /* mode 2 now ! */
- send_to_other_port( cpyfb( fbp ) );
- #endif
- if (!tol3sw(fbp)) /* Level 3 UI-Frame ? */
- dealmb(fbp); /* nein -> weg damit */
- continue; /* naechstes Frame */
- }
-
-
-
- /* Haben wir einen zum Frame passenden Linkblock ? */
- /* */
- /* Alle Linkbloecke durchgucken. Wenn ein aktiver Linkblock */
- /* gefunden wurde, dessen Quellcall mit dem Framezielcall */
- /* uebereinstimmt, tome auf TRUE setzen. Wenn auch noch Blockport */
- /* mit Frameport und Blockzielcall mit Framequellcall */
- /* uebereinstimmen, dann ist der aktive passende Link gefunden, */
- /* Schleife abbrechen. */
- /* */
- /* Falls ein Link inaktiv ist, aber das Framezielcall an mich */
- /* (Call + SSID oder Ident mit beliebiger SSID) ist, oder das */
- /* Blockquellcall mit dem Framezielcall uebereinstimmt, dann */
- /* Blockadresse in lblkp merken. Es wird nur der erste solche */
- /* Block genommen. */
-
- for ( tome = NO, lblkp = NULL, n = 0, lnkpoi = lnktbl;
- n < LINKNMBR;
- ++n, ++lnkpoi
- )
- if (lnkpoi->state != L2SDSCED)
- {
- if (cmpid(lnkpoi->srcid,rxfhdr) /* == TRUE */ )
- {
- tome = YES;
- if ( lnkpoi->liport == rxfprt
- && cmpid(lnkpoi->dstid,rxfhdr + L2IDLEN) /* == TRUE */
- ) break;
- }
- }
- else
- if ( !lblkp
- && ( ( *lnkpoi->srcid == '\0'
- && istome(rxfhdr) /* == TRUE */
- )
- || ( *lnkpoi->srcid != '\0'
- && cmpid(lnkpoi->srcid,rxfhdr) /* == TRUE */
- )
- )
- ) lblkp = lnkpoi;
-
-
- if (n == LINKNMBR) /* wenn kein aktiver Link */
- if (lblkp) /* passst, aber inaktiver */
- lnkpoi = lblkp; /* Link, dann diesen nehmen */
- else
- { /* sonst, wenn trotzdem das */
- if ( tome == YES /* Frame an mich gerichtet */
- || istome(rxfhdr) /*== TRUE ist, reagieren : */
- )
- {
- #ifdef STATSCMD
- L2RXCNT[fbp->l2port & MAXPORTMASK]++; /* recvd ++ */
- #endif
- if (rxfctl == L2CSABM) /* SABM mit DM beantworten */
- { /* und hoeheren Leveln */
- l2tolx(L2MBUSYT); /* melden */
- xdm();
- }
- else /* sonst nur antworten, wenn */
- if ( rxfPF != 0 /* Command mit Poll, dann */
- && rxfCR != 0 /* mit DM antworten */
- ) xdm();
- else /* oder wenn kein Command */
- if (rxfctl == L2CDISC) /* Poll, aber ein DISC, mit */
- xua(); /* UA antworten */
- }
- #ifdef KISSMODE
- else if( (crlmod == 2) && !ishost() && nmbfre > 64 )
- {
- send_to_other_port( fbp );
- continue;
- }
- #endif
- dealmb(fbp); /* empfangenes Frame weg- */
- continue; /* werfen und zum naechsten */
- }
-
-
-
- /* Falls Timer 3 aktiv, diesen neu setzen, es ist wieder */
- /* Aktivitaet auf dem Link */
-
- #ifdef STATSCMD
- L2RXCNT[fbp->l2port & MAXPORTMASK]++; /* bump recvd packet count*/
- #endif
-
- if (lnkpoi->T3 != 0) setT3();
-
-
- l2state = lnkpoi->state; /* Linkstatus zur Abfrage */
-
- if (!(rxfctl & L2CNOIM)) /* I-Frame ? */
- {
-
- /* I-Frame : */
- /* */
- /* Nur annehmen, wenn empfangene N(R) des Frames ok, */
- /* srxdNR(), und das I-Frame das naechste erwartete in der */
- /* Sequenz ist, isntxi(). */
- /* Wenn alles ok, Laenge pruefen und ggf. auf falsche Laenge */
- /* mit Frame-Reject reagieren, sonst Antwort entsprechend */
- /* Statetable und I-Frame verarbeiten. */
-
- if ( srxdNR() /*== TRUE*/ /* N(R) ok ? */
- && isnxti() /*== TRUE */ /* erwartet ? */
- )
-
- /* if support for soft MTUs is required ( as defined by */
- /* MOD_MTU ) then use RAM version instead of fixed value */
-
- #ifdef MOD_MTU
- if (fbp->mbpc - fbp->mbgc <= mtu_i_max) /* Laengenpruefung */
- #else
- if (fbp->mbpc - fbp->mbgc <= 257) /* Laengenpruefung */
- #endif
- {
- l2stma(!rxfPF ? stbl01 : stbl00); /* Statetable */
-
- /* Linkzustand I-Transfer moeglich und nicht busy ? */
-
- if (l2state >= L2SIXFER && !(lnkpoi->flag & L2FBUSY))
- {
-
- /* wenn Level-3-I-Paket, dann in Level-3-RX-Liste */
- /* einhaengen und Link als Level-3-Link markieren, */
- /* No-Activity-Timeout neu starten */
-
- if (tol3sw(fbp) /*== YES*/)
- {
- lnkpoi->flag |= L2FL3LNK;
- lnkpoi->noatou = ininat;
- }
- else
-
- /* wenn normales Level-2-I-Paket, wenn nicht Busy */
- /* oder Level-3-Link, I annehmen und in */
- /* Linkempfangsliste einhaengen */
-
- if (!(lnkpoi->flag & (L2FDSLE | L2FL3LNK)))
- {
- relink(fbp,lnkpoi->rcvdil.tail);
- ++lnkpoi->rcvd;
- }
- else
- dealmb(fbp); /* ansonsten Paket wegwerfen */
- continue; /* auf zum naechsten Paket */
- }
- }
- else /* Frame zu lang : */
- sdfrmr(0x03); /* "U/S-Frame mit unerlaubtem */
- /* Infofeld" */
- }
-
-
-
- else /* kein I-Frame : */
- if (!(rxfctl & L2CNOSM))
- {
-
- /* S-Frame : */
- /* */
- /* Nur annehmen, wenn empfangene N(R) des Frames ok, */
- /* srxdNR(), und wenn das Frame kein Infofeld enthaelt. */
- /* */
- /* Auf RR, RNR, REJ entsprechend Statetable antworten, auf */
- /* andere mit Frame-Reject antworten. */
-
- if (srxdNR() /*== YES*/) /* N(R) ok ? */
- if (fbp->mbgc == fbp->mbpc) /* kein I-Feld ? */
- switch ((rxfctl >> 2) & 0x03)
- {
-
- case 0 : /* L2CRR >> 2 */
- l2stma( !rxfCR
- ? (!rxfPF ? stbl11 : stbl10)
- : (!rxfPF ? stbl03 : stbl02)
- );
- break;
-
- case 1 : /* L2CRNR >> 2 */
- #ifdef STATSCMD
- L2RXRNR[fbp->l2port & MAXPORTMASK]++; /* recvd RNR */
- #endif
- l2stma( !rxfCR
- ? (!rxfPF ? stbl15 : stbl14)
- : (!rxfPF ? stbl07 : stbl06)
- );
- break;
-
- case 2 : /* L2CREJ >> 2 */
- #ifdef STATSCMD
- L2RXREJ[fbp->l2port & MAXPORTMASK]++; /* recvd REJ */
- #endif
- l2stma( !rxfCR
- ? (!rxfPF ? stbl13 : stbl12)
- : (!rxfPF ? stbl05 : stbl04)
- );
- if (l2state >= L2SIXFER) sdoi();
- break;
-
- default :
- sdfrmr(0x01); /* "Kontrollfeld falsch oder */
- break; /* nicht implementiert" */
-
- } /* end switch ((rxfctl >> 2) & 0x03) */
- else
- sdfrmr(0x03); /* "U/S-Frame mit unerlaubtem */
- /* Infofeld" */
- } /* end S-Frame */
-
-
-
- else /* kein I- oder S-Frame : */
- if ((rxfctl & 0xFF) != L2CFRMR)
-
- /* Kein FRMR-Frame, Frame nur annehmen, wenn kein Infofeld */
- /* vorhanden. */
- /* */
- /* Frame auswerten, reagieren, nach Statetable antworten. */
-
- if (fbp->mbgc == fbp->mbpc)
- switch (rxfctl)
- {
-
-
-
- case L2CSABM : /* neuer Link / Linkreset */
- lnkpoi->V2link = rxfV2; /* Protokollversion merken */
- switch (l2state)
- { /* neuer Link (Connect) ? */
- case L2SDSCED :
- if ( fvalca(VCpar,rxfhdr + L2IDLEN) == TRUE
- && nmblks < Ypar
- #ifdef ACL
- && !(( acl_mask & ACL_BAR_L2_IC ) &&
- (acl_entry(rxfhdr+L2IDLEN)&ACL_BAR_L2_IC))
- #endif
- #ifdef MODIFIED
- && !( (no_digi & 1) && *(rxfhdr+L2ILEN) )
- #endif
- && nmbfre > 128 /* annehmbar ? */
- )
- {
- inilnk(); /* ja, Link init. */
- ++nmblks; /* neuer Link */
- l2tolx(L2MCONNT); /* melden */
- #ifdef MANAGED
- l2audit( AudCon ); /* audit connect */
- #endif
- lnkpoi->noatou = ininat;
- #ifdef MODIFIED
- /* if help message enabled for i/c connects
- * and the connect is to the alias, force a
- * connection to the level 7 switch
- * Also, if extra aliases are enabled, check
- * for them & kick upstairs if located
- */
- if((( hlpflg & 8 ) && cmpcal( alias, rxfhdr ))
- ||
- ( enaliases && ( cmpcal( bbsalias, rxfhdr )
- || cmpcal( hostalias, rxfhdr )
- || cmpcal( dxcalias, rxfhdr ))))
- {
- relink(fbp,lnkpoi->rcvdil.tail);
- ++lnkpoi->rcvd;
- l2stma(stbl08);
- continue;
- }
- else
- #endif
- break; /* -> Statetable */
- }
- l2tolx(L2MBUSYT); /* nein, melden */
- xdm(); /* mit DM antwort. */
- dealmb(fbp); /* Frame vergessen */
- continue; /* naechstes Paket */
- break;
-
- case L2SLKSUP : /* beide connecten */
-
- /* anderer Weg als selbst benutzt ? */
-
- if ( !cmpidl( cmpid(rxfhdr + L2IDLEN,
- lnkpoi->srcid) /*== TRUE*/
- ? rxfhdr + L2ILEN
- : txfhdr + L2ILEN,
- lnkpoi->viaidl
- )
- )
- {
- clrlnk(); /* ja, alles */
- l2tolx(L2MBUSYF); /* abbrechen */
- xdm();
- lnkpoi->state = L2SDSCED;
- dealmb(fbp);
- continue;
- }
- else
- {
- reslnk(); /* nein, */
- l2tolx(L2MCONNT); /* gelungener */
- lnkpoi->noatou = ininat; /* Connect */
- }
- break;
-
- case L2SDSCRQ : /* sind ge-disct, Link */
- mclrlk(); /* aufloesen und melden */
- break;
-
- default : /* normaler Linkreset */
- inilnk(); /* vom Partner */
- l2tolx(L2MLRESF);
- break;
-
- } /* end switch (l2state) */
- l2stma(stbl08); /* SABM EITHER COMMAND */
- break;
-
-
-
- case L2CDISC :
- if (!l2state) /* Link aktiv ? */
- {
- if ( rxfPF != 0 /* nein, wenn Command */
- && rxfCR != 0 /* mit Poll, dann mit */
- ) xdm(); /* DM antworten */
- else
- xua(); /* sonst mit UA */
- dealmb(fbp); /* Frame wegwerfen */
- continue; /* naechstes Paket */
- }
- else /* ja, */
- {
- #ifdef MANAGED
- l2audit( AudDisc ); /* audit disconnect msg */
- #endif
- if (l2state == L2SLKSUP) /* wenn im Linkaufbau, */
- { /* dann Link sofort */
- clrlnk(); /* aufloesen und melden */
- l2tolx(L2MBUSYF);
- }
- else /* sonst erst restliche */
- { /* I-Frames an hoeheren */
- i2tolx(YES); /* Level geben und dann */
- mclrlk(); /* Link loesen / melden */
- }
- }
- l2stma(stbl09); /* DISC EITHER COMMAND */
- break;
-
-
-
- case L2CUA :
- if (l2state < L2SRS) /* V1-Zustand ? */
- {
- if (l2state == L2SLKSUP) /* ja, wenn im */
- { /* Link-Setup */
- lnkpoi->V2link = rxfV2; /* Protokollvers. */
- reslnk(); /* uebernehmen, */
- l2tolx(L2MCONNT); /* Link neu und */
- #ifdef MANAGED
- l2audit( AudConAcc ); /* audit connect accept*/
- #endif
- lnkpoi->noatou = ininat; /* melden */
- }
- else /* sonst wenn im */
- if (l2state == L2SDSCRQ) /* Disc-Request */
- {
- #ifdef MANAGED
- l2audit( AudDiscAcc ); /* audit disc accept */
- #endif
- mclrlk(); /* Link aufloesen */
- }
- }
- else
- {
- reslnk(); /* nein, Linkreset */
- l2tolx(L2MLREST); /* ausf. / melden */
- }
- l2stma(stbl16); /* UA EITHER RESPONSE */
- break;
-
-
-
- case L2CDM :
- if (l2state) /* wenn Link aktiv ... */
- if (l2state == L2SLKSUP) /* wenn DM beim Link- */
- { /* Setup, dann Link */
- clrlnk(); /* sofort aufloesen und */
- l2tolx(L2MBUSYF); /* "Busy from" melden */
- }
- else /* sonst Link aufloesen */
- mclrlk(); /* mit Meldung */
- l2stma(stbl17); /* DM EITHER RESPONSE */
- break;
-
-
-
- default : /* unbekanntes Kontrollfeld : */
- sdfrmr(0x01); /* "Kontrollfeld falsch oder */
- break; /* nicht implementiert" */
-
-
-
- } /* end switch (rxfctl) */
- else /* Frametyp unbekannt */
- sdfrmr(0x03); /* "U/S-Frame mit un- */
- /* erlaubtem Infofeld" */
-
-
-
- else /* from if (rxfctl != L2CFRMR) */
- {
-
- /* FRMR-Frame : */
- /* */
- /* Wird nur im Frame-Reject-Zustand oder bei moeglichem */
- /* Informationstransfer angenommen. */
- /* Es werden die FRMR-Infobytes gelesen, FRMR an die */
- /* hoeheren Level gemeldet, nach Statetable geantwortet. */
-
- if (l2state >= L2SIXFER || l2state == L2SFRREJ)
- {
- /* FRMR-Infobytes im Linkblock merken */
- for (source = lnkpoi->frmr, n = 3; n != 0; --n)
- *source++ = (fbp->mbgc < fbp->mbpc) ? getchr(fbp) : 0;
- l2tolx(L2MFRMRF);
- }
- l2stma(stbl18); /* FRMR EITHER RESPONSE */
-
- }
-
-
-
- dealmb(fbp); /* aktuelles Frame verarbeitet, wegwerfen */
-
- } /* end while ((fbp = rxfl.head) != &rxfl) */
- }
-
-
-
-
-
- /**************************************************************************\
- * *
- * "level 2 rest" *
- * *
- * Fuer alle aktiven Links Busyzustand pruefen/setzen/aufloesen, I-Pakete *
- * unter Beruecksichtigung der "Erstickungskontrolle" an hoehere Level *
- * weiterreichen. Fall Zustand "Disconnecten nach Uebertragung der *
- * restlichen I-Pakete" und keine I-Pakete mehr zu senden, Disconnect *
- * einleiten. *
- * Muellbufferliste frei machen (aus Interruptroutinen entstandener Muell, *
- * der besser ausserhalb der Interrupts deallokiert wird aus Zeitgruenden). *
- * *
- \**************************************************************************/
-
- VOID l2rest()
- {
- register unsigned n;
-
-
- for (n = 0, lnkpoi = lnktbl; n < LINKNMBR; ++n, ++lnkpoi)
- if (lnkpoi->state != L2SDSCED)
- {
-
- /* fuer alle aktiven (= nicht disconnecteten) Links : */
-
-
- txfV2 = lnkpoi->V2link; /* Protokollversion */
-
- /* wenn Zustand "nachdem alle restliche I's uebertragen wurden, */
- /* disconnecten" und alle I's uebertragen, DISC einleiten */
-
- if ( ((lnkpoi->flag & L2FDSLE) != NO)
- && !lnkpoi->tosend
- ) disc();
-
- /* sonst empfangene I-Pakete an hoeheren Level uebertragen und */
- /* Busy-Condition pruefen / setzen / aufheben */
- /* */
- /* "Busy werden" - weniger als 80 Freibuffer */
- /* oder so viele I-Pakete empfangen und */
- /* nicht abgeholt, wie */
- /* "Erstickungszaehler" conctl angibt */
- /* */
- /* "Busy aufloesen" - wieder mehr als 112 Freibuffer */
- /* und weniger als halb so viele */
- /* empfangen und nicht abgeholt wie */
- /* conctl angibt */
-
- else
- {
- i2tolx(NO);
- if (!(lnkpoi->flag & L2FBUSY)) /* nicht busy */
- {
- if (nmbfre < 80 || lnkpoi->rcvd >= conctl)
- {
- lnkpoi->flag |= L2FBUSY; /* busy werden */
- l2stma(stbl21); /* STATION BECOMES BUSY */
- }
- }
- else
- if (nmbfre > 112 && lnkpoi->rcvd < conctl/2)
- {
- lnkpoi->flag &= ~L2FBUSY; /* "busy" aufloesen */
- l2stma(stbl22); /* BUSY CONDITION CLEARS */
- }
- }
- } /* end if (lnkpoi->state) */
-
- dealml(&trfl); /* Muellbufferliste frei machen */
- }
-
-
-
-
-
- /**************************************************************************\
- * *
- * "level 2 timer" *
- * *
- * Ausfuehren der Level-2-Millisekundentimer 1, 2, 3 in allen aktiven *
- * Links (herunterzaehlen und bei Ablauf reagieren). *
- * In ticks wird die Anzahl der vergangenen 10ms-Intervalle (Ticks) seit *
- * dem letzten Aufruf dieser Routine angegeben. *
- * *
- \**************************************************************************/
-
- VOID l2timr(ticks)
- register unsigned ticks;
- {
- register unsigned n;
-
- for (n = LINKNMBR, lnkpoi = lnktbl; n != 0; --n, ++lnkpoi)
- if (lnkpoi->state != L2SDSCED)
- {
-
- /* fuer alle aktiven (= nicht disconnecteten) Links : */
-
-
- txfV2 = lnkpoi->V2link; /* Merker ob Version-2-Protokoll */
-
- if (lnkpoi->T1 != 0) /* wenn Timer 1 aktiv ... */
- if (lnkpoi->T1 <= ticks) /* wenn Timer 1 abgelaufen ... */
- {
- lnkpoi->T1 = 0; /* ... Timer 1 stoppen */
- setT3(); /* Timer 3 neu starten */
- ++lnkpoi->tries; /* Retryzaehler */
- if ( !lnkpoi->N2
- || lnkpoi->tries < lnkpoi->N2 /* zu viele Retries ? */
- )
- if ( lnkpoi->V2link == YES /* nein, bei V2 oder */
- || lnkpoi->state < L2SIXFER /* V1-Status < IXFER */
- ) l2stma(stbl23); /* Statet. T1 EXPIRES */
- else /* sonst ausstehende */
- sdoi(); /* I's senden */
- else
- { /* zu viele Retries : */
- #ifdef STATSCMD
- L2FAILS[lnkpoi->liport & MAXPORTMASK]++; /* link failed */
- #endif
- lnkpoi->tries = 0; /* Retryzaehler leer */
- clrlnk(); /* Link sofort loesch. */
- l2tolx(L2MFAILW); /* "Link failure" */
- lnkpoi->state = L2SDSCED; /* DISCONNECTED */
- }
- }
- else
- lnkpoi->T1 -= ticks; /* sonst herunterzaehlen */
-
- if (lnkpoi->T2 != 0) /* wenn Timer 2 aktiv ... */
- if (lnkpoi->T2 <= ticks) /* wenn Timer 2 abgelaufen ... */
- lnkpoi->T2 = 0; /* ... Timer 2 stoppen */
- else
- lnkpoi->T2 -= ticks; /* sonst herunterzaehlen */
-
- if ( !lnkpoi->T2 /* wenn Timer 2 abgelaufen ist */
- && lnkpoi->RStype != 0 /* und Response zu senden ist */
- && !iscd(lnkpoi->liport) /* und der Kanal frei ist ... */
- )
- {
- stxfad(); /* ... dann Responseframe bauen */
- txfCR = txfPF = 0;
- txfctl = setNR( !(lnkpoi->flag & L2FBUSY)
- ? lnkpoi->RStype
- : L2CRNR
- );
- sdl2fr(makfhd(L2FUS)); /* und senden */
- lnkpoi->RStype = 0; /* Responsemodus loeschen */
- }
-
- if (lnkpoi->T3 != 0) /* wenn Timer 3 aktiv ... */
- if (lnkpoi->T3 <= ticks) /* wenn Timer 3 abgelaufen ... */
- {
- clrT3(); /* ... Timer 3 stoppen und */
- l2stma(stbl24); /* Statetable T3 EXPIRES */
- } /* ausfuehren */
- else
- lnkpoi->T3 -= ticks; /* sonst herunterzaehlen */
-
- }
- }
-
- /**************************************************************************\
- * *
- * "kiss mode driver support" *
- * *
- * This function sends a packet to the other port ( came in on HDLC, *
- * ie port 0 , goes out on port 1, RS232 ) and vica versa *
- * *
- \**************************************************************************/
-
- #ifdef KISSMODE
- send_to_other_port(fbp)
- register MBHEAD *fbp;
- {
- fbp->l2port ^= 1; /* change port 0 -> 1 and 1 -> 0 */
- fbp->l2fflg = 0;
- sdl2fr( fbp ); /* send the packet */
- }
- #endif
-
- /**************************************************************************\
- * *
- * "level 2 audit handler" *
- * *
- * This function audits a connection or disconnection for a level 2 *
- * connection by sending a notify message to all ccp users at level 6 *
- * *
- \**************************************************************************/
-
- #ifdef MANAGED
- l2audit( what )
- char *what;
- {
- if( auditmask & 2 )
- notify( L2audit, 6, lnkpoi->srcid, lnkpoi->dstid, what, 2 );
- }
- #endif
-
- /* Ende von L2A.C */